﻿using System.Net;
using System.Net.Sockets;
using System.Text;

class Program
{
    private static bool _isRunning = false;
    private const string _ipAddress = "127.0.0.1";
    private const int _port = 9527;
    private static Dictionary<int, NetworkStream> _clients = new Dictionary<int, NetworkStream>();

    static void Main()
    {
        Console.WriteLine($"IM Server now will start listening from ipaddress: {_ipAddress} port: {_port}");

        Start();
        new Task(async () => await Listening()).Start();

        while (_isRunning)
        {
            var input = Console.ReadLine();
            if (input == "exit")
            {
                Stop();
                Console.WriteLine("IM server now will exit!");
            }
        }
    }

    static void Start() => _isRunning = true;
    static void Stop() => _isRunning = false;

    /// <summary>
    /// 服务器端对于固定端口号的监听
    /// </summary>
    /// <returns></returns>
    static async Task Listening()
    {
        Console.WriteLine($"服务器端将启动对 {_ipAddress} 端口号 {_port} 的监听!");
        var listener = new TcpListener(IPAddress.Parse(_ipAddress), _port);
        listener.Start();

        while (_isRunning)
        {
            try
            {
                Console.WriteLine($"服务器端已启动端口号 {_port} 的监听, 等待客户端的链接!");
                using var client = listener.AcceptTcpClient();
                using var stream = client.GetStream();
                if (stream.CanWrite)
                {
                    Console.WriteLine($"客户端 {client.Client.RemoteEndPoint} 已连接到服务器端口号 {_port}, 将发送随机端口号给客户端!");
                    var random = new Random();
                    var port = random.Next(10000, 20000);
                    while (_clients.ContainsKey(port))
                    {
                        port = random.Next(10000, 20000);
                    }

                    Console.WriteLine($"将发送随机端口号 {port} 给客户端 {client.Client.RemoteEndPoint}!");
                    await stream.WriteAsync(BitConverter.GetBytes(port));
                    Console.WriteLine($"已发送随机端口号 {port} 给客户端 {client.Client.RemoteEndPoint}!");

                    stream.Close();
                    client.Close();

                    new Task(async () => await ClientListening(port), TaskCreationOptions.LongRunning).Start();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                break;
            }
        }

        listener.Stop();
    }

    /// <summary>
    /// 服务器端对于 port 端口号客户端连接的监听
    /// </summary>
    /// <param name="port"></param>
    /// <returns></returns>
    static async Task ClientListening(int port)
    {
        try
        {
            Console.WriteLine($"服务器端将启动对 {_ipAddress} 端口号 {port} 的监听!");
            var listener = new TcpListener(IPAddress.Parse(_ipAddress), port);
            listener.Start();
            Console.WriteLine($"服务器端已启动端口号 {port} 的监听, 等待客户端的链接!");

            using var client = listener.AcceptTcpClient();
            Console.WriteLine($"客户端 {client.Client.RemoteEndPoint} 已经连接到端口号: {port}");
            using var stream = client.GetStream();
            _clients.Add(port, stream);
            var buffer = new byte[1024];

            while (_isRunning && client.Connected && stream.CanRead)
            {
                try
                {
                    Console.WriteLine($"等待来自客户端 {port} 的消息...");
                    var length = await stream.ReadAsync(buffer);
                    var message = Encoding.UTF8.GetString(buffer, 0, length);
                    if (message != null && !string.IsNullOrWhiteSpace(message))
                    {
                        Console.WriteLine($"收到来自客户端 {port} 的消息: {message}");
                        Task.Run(async () => await Send(port, message)).Start();
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                finally
                {
                    await Task.Delay(100);
                }
            }

            stream.Close();
            client.Close();
            Console.WriteLine($"客户端 {client.Client.RemoteEndPoint} 已断开端口号: {port} 的链接");
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

    /// <summary>
    /// 服务器端转发消息到客户端
    /// </summary>
    /// <param name="port"></param>
    /// <param name="message"></param>
    static async Task Send(int port, string message)
    {
        var clients = _clients.Where(x => x.Key != port);
        if (clients.Any())
        {
            Console.WriteLine($"将发送消息 {message} 到客户端 {string.Join(", ", clients.Select(x => x.Key))}");
            foreach (var keyValuePair in clients)
            {
                try
                {
                    var stream = keyValuePair.Value;
                    if (stream.CanWrite)
                    {
                        var buffer = Encoding.UTF8.GetBytes(message);
                        await stream.WriteAsync(buffer, 0, buffer.Length);
                        Console.WriteLine($"已发送消息 {message} 到客户端 {keyValuePair.Key}");
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }
    }
}